package cn.lg.soar.core.excel.strategy;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.Map;
import java.util.Objects;

/**
 * 多列行合并策略
 * @author luguoxiang
 * @date 2021/9/25
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class RowMergeStrategy extends AbstractMergeStrategy {

	/**
	 * 最后一行索引
	 */
	private int lastRowIndex = -1;
	/**
	 * 需要做合并处理的列
	 */
	private final Map<Integer, Info> map = new HashedMap<>();

	/**
	 * @param dataLength 数据行数
	 * @param mergeColIndexes 需要做合并处理的列
	 */
	public RowMergeStrategy(int dataLength, int... mergeColIndexes) {
		this.lastRowIndex = dataLength - 1;
		if (mergeColIndexes == null || mergeColIndexes.length == 0) {
			throw new IllegalArgumentException("mergeCellIndexes cannot be null or empty");
		}
		for (int x : mergeColIndexes) {
			this.map.put(x, new Info());
		}
	}

	@Override
	protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
		int currentCellIndex = cell.getColumnIndex();
		Info info = map.get(currentCellIndex);
		if (info == null) {
			return;
		}
		// 是否行值相同
		if (Objects.equals(info.lastValue, cell.getStringCellValue())) {
			info.count++;
			// 是否最后一行
			if (lastRowIndex == relativeRowIndex) {
				// 是最后一行将下标偏移到下一行（为了和非最后一行合并的计算方式一致）
				relativeRowIndex += 1;
			} else {
				return;
			}
		}
		// 与前一行值不同，对前面的数据做合并
		if (info.count > 0) {
			CellRangeAddress address = new CellRangeAddress(relativeRowIndex - info.count, relativeRowIndex, currentCellIndex, currentCellIndex);
			// 合并依据相同
			sheet.addMergedRegionUnsafe(address);
		}
		// 更新
		info.lastValue = cell.getStringCellValue();
		info.count = 0;
	}

	private static class Info {
		private int count = 0;
		private String lastValue = null;
	}

}


